package com.xixibaby.core.message;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.xixibaby.core.Assert;
import com.xixibaby.core.SpringUtil;

import java.util.*;
import java.util.function.Function;

public abstract class BaseChannel implements Channel<ExeObj>{

    private boolean aysn = false;
    private String targetField;
    private String[] format;
    private boolean daymic = false;
    private Delay delay = new Delay(new Date(),-1);

    private String id;
    //动态获取发送目标的能力
    private TargetFunction daymicTarget;

    public BaseChannel(){
        this.id = RandomUtil.randomString(12).toUpperCase();
    }

    @Override
    public TargetFunction daymicTarget() {
        return this.daymicTarget;
    }



    @Override
    public boolean isDaymic() {
        return daymic;
    }

    @Override
    public Channel<ExeObj> target(TargetFunction function) {
        this.daymic = true;
        this.daymicTarget = function;
        this.targetField = "daynmic";
        return this;
    }

    @Override
    public Channel<ExeObj> target(String filed) {
        this.targetField = filed;
        return this;
    }

    @Override
    public String target() {
        return this.targetField;
    }

    protected String[] format() {
        if(Assert.notEmpty(this.format)){
            return this.format;
        }
        return this.defaultFormat();
    }

    protected String[] defaultFormat(){
        return null;
    };

    @Override
    public Channel<ExeObj> format(String[] strings) {
        this.format = strings;
        return this;
    }


    @Override
    public List<Boolean> handler(String[] target, Map<String, Object> context) {

        ChannelHandler channelSend = SpringUtil.getBean(ChannelHandler.class, this.code());
        //对参数进行特定处理
        this.beforeHandler(context);
        //对参数进行format
        this.format(context);
        //执行具体的发送事件
        List<Boolean> handler = channelSend.handler(target, context);
        //添加的参数需要进行清除
        this.cleanMap(context);
        return handler;
    }


    private void format(Map<String, Object> context){
        String[] fields = this.format();
        if(Assert.notEmpty(fields) && fields.length == 2){
            String field = fields[0];
            String values = fields[1];
            Object o = context.get(field);
            Assert.succ(o).thenThrow("指定的[{}]值在参数中不存在",field);
            Object s = context.get(values);
            Assert.succ(s).thenLogError("指定的["+values+"]值在参数中不存在");
            String format;
            if(null != s && s.getClass().isArray()){
                Object[] objects = (Object[]) s;
                format = StrUtil.format(o.toString(), objects);
            }else if(null != s){
                format = StrUtil.format(o.toString(), s);
            }else{
                format = o.toString();
            }
            context.put(field,format);
        }
    }


    protected void cleanMap(Map<String, Object> context){

    }

    protected void beforeHandler(Map<String, Object> context){

    }


    @Override
    public Channel<ExeObj> delay(Date date, Integer seconds) {
        this.aysn = true;
        this.delay.setDate(date);
        this.delay.setDelay(seconds);
        return this;
    }

    @Override
    public Channel<ExeObj> delay(String date, Integer seconds) {
        this.aysn = true;
        DateTime parse = DateUtil.parse(date, DatePattern.NORM_DATETIME_PATTERN);
        return this.delay(parse,seconds);
    }

    @Override
    public Channel<ExeObj> delay(Date date) {
        this.aysn = true;
        this.delay.setDate(date);
        return this;
    }

    @Override
    public Channel<ExeObj> delay(String date) {
        this.aysn = true;
        DateTime parse = DateUtil.parse(date, DatePattern.NORM_DATETIME_PATTERN);
        this.delay.setDate(parse);
        return this;
    }

    @Override
    public Channel<ExeObj> delay(Integer seconds) {
        this.aysn = true;
        this.delay.setDelay(seconds);
        return this;
    }

    @Override
    public Channel<ExeObj> aysn(boolean aysn) {
        this.aysn = aysn;
        this.delay = new Delay(new Date(),-1);
        return this;
    }

    @Override
    public Channel<ExeObj> sendDate(Date date) {
        this.aysn = true;
        Long ms = (date.getTime() - System.currentTimeMillis()) / 1000;
        this.delay.setDelay(ms.intValue());
        this.delay.setDate(new Date());
        return this;
    }

    @Override
    public Date sendDate() {
        return this.delay.getResultDate();
    }

    @Override
    public Delay delay() {
        return this.delay;
    }

    @Override
    public Integer seconds() {
        return this.delay.getDelayAsNow();
    }

    @Override
    public Date date() {
        return this.delay.getDate();
    }

    @Override
    public boolean aysn() {
        return this.aysn;
    }

    @Override
    public String id() {
        return id;
    }
}
